package com.bpzj.util.pdf;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URL;
import java.text.ParseException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

public class DIDITravelTripThird {
    static String applyDate = "2022-06-29";
    static BigDecimal totalPrice = new BigDecimal("136.80");
    static int step = 0;
    // 里程必是一位小数或两位小数：整数带 .0
    //    static String end = "万柳东路|万泉庄北社区-西门";
    static String end = "马连洼|镶黄旗万树园小区-东门";
    // "北清路|生命科学园-地铁站"   6.9   16.03

    // {"12-02 21:04", "用友路|用友产业园西区-北门", end, "13.5", "39.80"},
    // {"12-07 21:17", "用友路|用友产业园西区-北门", end, "13.7", "39.46"},
    // {"12-09 20:53", "用友路|用友产业园西区-北门", end, "13.6", "38.03"},
    // {"12-11 02:56", "用友路|用友产业园西区-北门", end, "13.4", ""},
    static String[][] tripTimeAndDistance = {
            {"2022-4-13 21:11", "用友路|用友产业园西区-北门", end, "8.6", "33.69"},
            {"2022-4-21 21:53", "用友路|用友产业园西区-北门", end, "8.7", "34.51"},
            {"2022-6-10 20:59", "用友路|用友产业园西区-北门", end, "8.73", "35.83"},
            {"2022-6-28 21:09", "用友路|用友产业园西区-北门", end, "8.5", ""},

            // {"09-23 21:10", "用友路|用友产业园西区-北门", end, "13.7", "38.40"},
            // {"09-27 21:03", "用友路|用友产业园西区-北门", end, "13.8", "39.93"},
            // {"10-16 16:49", "用友路|用友产业园西区-北门",  "北清路|生命科学园-地铁站", "6.9", "16.03"},
    };

    static String phoneNum = "17610089306";

    //    static String fontPath = "C:\\Users\\l\\Desktop\\msyh.ttf";
    static String fontPath = "C:\\Users\\Administrator\\Desktop\\msyh.ttf";
    //    static String fontPath = "msyh.ttf";
    static String tripStartDate;
    static String tripEndDate;

    static {
        try {
            tripStartDate = getStartDate(tripTimeAndDistance).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            tripEndDate = getEndDate(tripTimeAndDistance).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    private static LocalDateTime getEndDate(String[][] tripTimeAndDistance) throws ParseException {
        LocalDateTime date = getDate(tripTimeAndDistance[0][0]);
        for (int i = 1; i < tripTimeAndDistance.length; i++) {
            LocalDateTime date1 = getDate(tripTimeAndDistance[i][0]);
            if (date1.isAfter(date)) {
                date = date1;
            }
        }
        return date;
    }

    private static LocalDateTime getStartDate(String[][] tripTimeAndDistance) throws ParseException {
        LocalDateTime date = getDate(tripTimeAndDistance[0][0]);
        for (int i = 1; i < tripTimeAndDistance.length; i++) {
            LocalDateTime date1 = getDate(tripTimeAndDistance[i][0]);
            if (date1.isBefore(date)) {
                date = date1;
            }
        }
        return date;
    }

    static String tripCount = String.valueOf(tripTimeAndDistance.length);

    public static void main(String[] args) {
        create_pdf("第三方网约车服务公司_阳光出行行程报销单");

        // totalPrice = new BigDecimal("26.89");
        // tripTimeAndDistance = new String[][]{
        //         {"09-09 21:18", "用友路|用友产业园西区-北门", "马连洼|镶黄旗万树园小区-东门", "8.6", "26.89"},
        // };
        // calTripStartEndCount();
        // create_pdf("滴滴出行行程报销单B");

    }

    private static void calTripStartEndCount() {
        tripStartDate = "2021-" + tripTimeAndDistance[0][0].split(" ")[0];
        tripEndDate = "2021-" + tripTimeAndDistance[tripTimeAndDistance.length - 1][0].split(" ")[0];
        tripCount = String.valueOf(tripTimeAndDistance.length);
    }

    private static void create_pdf(String fileName) {
        Document document = new Document(PageSize.A4, 0, 0, 0, 0);
        try {
            // creation of the different writers
            //            HtmlWriter.getInstance(document , System.out);
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(fileName + ".pdf"));
            // we add some meta information to the document
            // document.addSubject("This is the result of a Test.");
            // we open the document for writing
            document.open();
            addHeadPicture(document, writer);

            BaseFont yahei = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            addTableHeadInfo(writer);


            PdfPTable table = new PdfPTable(9);
            table.setTotalWidth(new float[]{25, 35, 65, 40, 120, 120, 40, 40, 35});
            table.setLockedWidth(true);
            table.getDefaultCell().setBorder(0);
            Font font = new Font(yahei, 8.5f, Font.UNDEFINED, new BaseColor(242, 242, 242));
            addHeadRow(table, new String[]{"序号", "车型", "上车时间", "城 市", "起点", "终点", "里程\n[公里]", "金额\n[元]", "备注"}, font);


            String totalPage = "1";
            String[][] writeTrips = getWriteTrips(tripTimeAndDistance);
            if (tripTimeAndDistance.length > 11) {
                String[][] before11 = new String[11][9];
                System.arraycopy(writeTrips, 0, before11, 0, 11);

                font = new Font(yahei, 7f, Font.UNDEFINED, new BaseColor(116, 116, 116));
                addContentUseTripTimeAndDistance(table, before11, font);
                totalPage = "2";
                fixPositionText(writer, "页码：1/" + totalPage, yahei, 8, 510.0f, 45.0f);
            } else {
                font = new Font(yahei, 7f, Font.UNDEFINED, new BaseColor(116, 116, 116));
                addContentUseTripTimeAndDistance(table, writeTrips, font);
                fixPositionText(writer, "页码：1/" + totalPage, yahei, 8, 510.0f, 45.0f);
            }

            table.writeSelectedRows(0, -1, 42.585f, 571.845f+69 - step, writer.getDirectContent());


            // 页码

            if (tripTimeAndDistance.length > 11) {
                document.newPage();
                addHeadPicture(document, writer);

                PdfPTable table2 = new PdfPTable(9);
                table2.setTotalWidth(new float[]{25, 35, 65, 40, 120, 120, 40, 40, 35});
                table2.setLockedWidth(true);
                table2.getDefaultCell().setBorder(0);
                font = new Font(yahei, 8.5f, Font.UNDEFINED, new BaseColor(242, 242, 242));
                addHeadRow(table2, new String[]{"序号", "车型", "上车时间", "城 市", "起点", "终点", "里程\n[公里]", "金额\n[元]", "备注"}, font);

                String[][] after11 = new String[writeTrips.length-11][9];
                System.arraycopy(writeTrips, 11, after11, 0, writeTrips.length - 11);
                font = new Font(yahei, 7f, Font.UNDEFINED, new BaseColor(116, 116, 116));
                addContentUseTripTimeAndDistance(table2, after11, font);
                table2.writeSelectedRows(0, -1, 42.585f, 571.845f + 136, writer.getDirectContent());
                fixPositionText(writer, "页码：2/" + totalPage, yahei, 8, 510.0f, 45.0f);
            }

            // img.setAbsolutePosition(0, 0);
            // document.add(img);
            //            document.add(table);
            //            document.add(paragraph);
        } catch (DocumentException | FileNotFoundException de) {
            System.err.println(de.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
        document.close();
    }

    private static void addJianDaoPicture(Document document, PdfWriter writer) throws DocumentException, IOException {
        Image logo = Image.getInstance(Thread.currentThread().getContextClassLoader().getResource("jiandao.png"));
        logo.setAbsolutePosition(0F, 595.75f);
        logo.scalePercent(37.4918f, 35f); // x 是宽度
        document.add(logo);
    }

    private static void addTuiGuangPicture(Document document, PdfWriter writer) throws IOException, DocumentException {
        Image logo = Image.getInstance(Thread.currentThread().getContextClassLoader().getResource("didi-logo-2-2.png"));
        logo.setAbsolutePosition(40, 630);
        logo.scalePercent(25.1208f, 25.0556f); // x 是宽度
        document.add(logo);

        //        URL didi = Thread.currentThread().getContextClassLoader().getResource("didi-logo-2.jpg");
        //        Image logo = Image.getInstance(didi);
        //        float width = logo.getScaledWidth();
        //        float height = logo.getScaledHeight();
        //        PdfTemplate template = writer.getDirectContent().createTemplate(width, height - 1);
        //        template.addImage(logo, width, 0, 0, height, 0, 0);
        //        Image didiHead = Image.getInstance(template);
        //        didiHead.setAbsolutePosition(40, 630);
        //        didiHead.scalePercent(25.1208f, 25.1256f); // x 是宽度
        //        document.add(didiHead);
    }

    private static void addTableHeadInfo(PdfWriter writer) throws DocumentException, IOException {
        BaseFont yahei = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);


        fixPositionText(writer, "第三方网约车服务提供方阳光出行—行程单", yahei, 23, 78.5f, 689 - step);
        float baseY = 667;
        verticalLine(writer, 2, BaseColor.BLACK, baseY - step, baseY + 6 - step, 43.5f);
        fixPositionText(writer, "申请日期:" + applyDate, yahei, 8, 47.5f, baseY - step);

        verticalLine(writer, 2, BaseColor.BLACK, baseY - step, baseY + 6 - step, 208.5f);
        fixPositionText(writer, "行程起止日期:" + tripStartDate + " 至 " + tripEndDate, yahei, 8, 212.5f, baseY - step);

        baseY = 651;
        verticalLine(writer, 2, BaseColor.BLACK, baseY - step, baseY + 6 - step, 43.5f);
        fixPositionText(writer, "行程人手机号:" + phoneNum, yahei, 8, 47.5f, baseY - step);

        verticalLine(writer, 2, BaseColor.BLACK, baseY - step, baseY + 6 - step, 208.5f);
        fixPositionText(writer, "共" + tripCount + "笔行程， 合计 " + totalPrice + "元", yahei, 8, 212.5f, baseY - step);
    }

    /**
     * 添加页面头图和 logo
     *
     * @param document
     * @param writer
     * @throws IOException
     * @throws DocumentException
     */
    private static void addHeadPicture(Document document, PdfWriter writer) throws IOException, DocumentException {
        URL didi = Thread.currentThread().getContextClassLoader().getResource("didi-head-1.png");
        Image image = Image.getInstance(didi);
        // 裁剪图片 https://stackoverflow.com/questions/8134421/cropping-images-in-itext
        float width = image.getScaledWidth();
        float height = image.getScaledHeight();
        PdfTemplate template = writer.getDirectContent().createTemplate(width, height - 8);
        // 这几个参数的含义 https://stackoverflow.com/questions/45930261/what-are-the-meanings-of-itextpdf-pdfcontentbyte-addtemplates-parameters
        template.addImage(image, width, 0, 0, height, 0, 0);
        Image didiHead = Image.getInstance(template);
        didiHead.setAlignment(Element.ALIGN_CENTER);
        document.add(didiHead);
    }

    private static void addContentUseTripTimeAndDistance(PdfPTable table, String[][] writeTrips, Font font) throws Exception {
        for (int i = 0; i < writeTrips.length; i++) {
            String[] row = writeTrips[i];
            if (Integer.parseInt(row[0]) % 2 != 0) {
                addBodyRow(table, row, font, BaseColor.WHITE);
            } else {
                addBodyRow(table, row, font, new BaseColor(240, 240, 240));
            }
        }
    }

    private static String[][] getWriteTrips(String[][] trips) throws Exception {
        String[][] result = new String[trips.length][9];
        for (int i = 0; i < trips.length; i++) {
            LocalDateTime time = getDate(trips[i][0]);
            if (i == trips.length - 1 && LocalDate.parse(applyDate).isBefore(time.toLocalDate())) {
                throw new Exception("申请日期错误");
            }
            LocalDateTime tripTime = time.plusMinutes(new Random().nextInt(10) + 3);
            String timeWithWeek = tripTime.format(DateTimeFormatter.ofPattern("MM-dd HH:mm ")) + getWeek(time.toLocalDate());
            String itemPrice = getPrice(trips[i][4], i, trips.length);
            String[] row = {"", "阳光快车", timeWithWeek, "北京市", trips[i][1], trips[i][2], trips[i][3], itemPrice, ""};
            result[i] = row;
        }
        List<String[]> collect = Arrays.stream(result).sorted(Comparator.comparing(a -> a[2])).collect(Collectors.toList());
        for (int i = 0; i < collect.size(); i++) {
            collect.get(i)[0] = String.valueOf(i + 1);
        }
        return collect.toArray(result);
    }

    // todo
    private static LocalDateTime getDate(String time) throws ParseException {
        if (time.matches("\\d{1,2}-\\d{2} \\d{1,2}:\\d{2}")) {
            return LocalDateTime.parse(LocalDate.now().getYear() + "-" + time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        } else if (time.matches("\\d{4}-\\d-\\d \\d{1,2}:\\d{2}")) {
            return LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-M-d HH:mm"));
        } else if (time.matches("\\d{4}-\\d-\\d{1,2} \\d{1,2}:\\d{2}")) {
            return LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-M-dd HH:mm"));
        } else if (time.matches("\\d{4}-\\d{2}-\\d{1,2} \\d{1,2}:\\d{2}")) {
            return LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        } else {
            throw new ParseException("不支持的日期格式", 0);
        }
    }

    private static String getWeek(LocalDate localDate) {
        DayOfWeek dayOfWeek = localDate.getDayOfWeek();
        Map<Integer, String> weeks = new HashMap<>();
        weeks.put(1, "周一");
        weeks.put(2, "周二");
        weeks.put(3, "周三");
        weeks.put(4, "周四");
        weeks.put(5, "周五");
        weeks.put(6, "周六");
        weeks.put(7, "周日");
        return weeks.get(dayOfWeek.getValue());
    }

    // todo
    private static String getPrice(String price, int i, int length) {

        if (i < length - 1 && price != null && !price.equals("")) {
            totalPrice = totalPrice.subtract(new BigDecimal(price));
            return price;
        } else if (i == length - 1) {
            return totalPrice.toString();
        }
        return null;
    }

    private static void addBodyRow(PdfPTable table, String[] strings, Font font, BaseColor backgroundColor) {
        // 构建每个单元格
        for (int i = 0; i < strings.length; i++) {
            String string = strings[i];
            PdfPCell cell = new PdfPCell(new Paragraph(string, font));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            if (i == 0) {
                cell.setBorderWidthLeft(0.5f);
                cell.setBorderWidthRight(0);
            } else if (i == strings.length - 1) {
                cell.setBorderWidthLeft(0f);
                cell.setBorderWidthRight(0.5f);
            } else {
                cell.setBorderWidthLeft(0);
                cell.setBorderWidthRight(0);
            }
            cell.setBorderWidthTop(0);
            cell.setFixedHeight(31f);
            cell.setBorderColor(new BaseColor(208, 208, 208));
            cell.setBackgroundColor(backgroundColor);
            table.addCell(cell);
        }
    }


    private static void addHeadRow(PdfPTable table, String[] strings, Font font) {
        // 构建每个单元格
        for (int i = 0; i < strings.length; i++) {
            String string = strings[i];
            PdfPCell cell = new PdfPCell();
            if (string.contains("\n")) {
                String[] split = string.split("\n");
                for (String s : split) {
                    Paragraph paragraph = new Paragraph(s, font);
                    paragraph.setSpacingAfter(4.3f);
                    paragraph.setAlignment(Element.ALIGN_CENTER);
                    cell.addElement(paragraph);
                }
            } else {
                cell = new PdfPCell(new Paragraph(string, font));
            }
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            if (i == 0) {
                cell.setBorderWidthLeft(0.5f);
                cell.setBorderWidthRight(0);
            } else if (i == strings.length - 1) {
                cell.setBorderWidthLeft(0f);
                cell.setBorderWidthRight(0.5f);
            } else {
                cell.setBorderWidthLeft(0);
                cell.setBorderWidthRight(0);
            }
            cell.setFixedHeight(41.25f);
            cell.setBorderColor(new BaseColor(208, 208, 208));
            cell.setBackgroundColor(new BaseColor(102, 102, 102));
            table.addCell(cell);
        }
    }

    private static void verticalLine(PdfWriter writer, float lineWidth, BaseColor colorStroke, float bottomY, float topY, float x) {
        PdfContentByte canvas = writer.getDirectContent();
        canvas.saveState();
        canvas.setLineWidth(lineWidth);
        canvas.setColorStroke(colorStroke);
        canvas.moveTo(x, bottomY);
        canvas.lineTo(x, topY);
        canvas.stroke();
        canvas.restoreState();
    }

    public static void fixPositionText(PdfWriter writer, String text, BaseFont baseFont1, float fontSize, float x, float y) {
        fixPositionText(writer, text, baseFont1, fontSize, x, y, 0, 0, 0);
    }

    private static void fixPositionText(PdfWriter writer, String text, BaseFont baseFont1, float size, float x, float y, int r, int g, int b) {
        PdfContentByte cb = writer.getDirectContent();
        cb.saveState();
        cb.beginText();
        cb.moveText(x, y);
        cb.setFontAndSize(baseFont1, size);
        cb.setRGBColorFill(r, g, b);
        cb.showText(text);
        cb.endText();
        cb.restoreState();
    }
}
